home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / ScreenSaver / Q3ADUtilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  12.9 KB  |  615 lines  |  [TEXT/CWIE]

  1. #include "Q3ADUtilities.h"
  2.  
  3. #include <assert.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include <QD3DAcceleration.h>
  7.  
  8. #include <QDOffscreen.h>
  9.  
  10. /*
  11. ** CONSTANTS
  12. */
  13. #define        kSize    1.0
  14. #define        kSpace    1.0
  15.  
  16. /*
  17. **    GLOBALS for the following functions
  18. */
  19. unsigned long    gCurrentTicks = 0;
  20.  
  21. typedef struct iTQ3ADOffscreen {
  22.     GWorldPtr    sourcePort;
  23.     CGrafPtr    destPort;
  24.     Rect        destRect;
  25.     long        dithered;
  26.     
  27. }    iTQ3ADOffscreen;
  28.  
  29. static TQ3Status        iOffscreen_ZeroOut(
  30.                             iTQ3ADOffscreen *ioOffscreen);
  31.  
  32. TQ3RendererObject    Q3ADUtility_NewRenderer(void)
  33. {
  34.     TQ3RendererObject    returnRenderer = NULL;
  35.  
  36.     returnRenderer =    Q3Renderer_NewFromType(
  37.                             kQ3RendererTypeInteractive);
  38.     
  39.     if (!returnRenderer) goto bail;
  40.     
  41.     Q3InteractiveRenderer_SetDoubleBufferBypass (
  42.         returnRenderer,
  43.         kQ3False);                        
  44.  
  45.     Q3InteractiveRenderer_SetPreferences(
  46.             returnRenderer,
  47.             kQAVendor_BestChoice, 0);
  48.     
  49. bail:
  50.     return (returnRenderer);
  51. }
  52.  
  53. TQ3DrawContextObject    Q3ADUtility_NewMacDrawContext(
  54.                             CGrafPtr port,
  55.                             float paneSize)
  56. {
  57.     TQ3DrawContextObject    theDrawContext    = NULL;
  58.     TQ3ColorARGB            white    = { 1.0, 0.0, 0.0, 0.0 };
  59.     TQ3Status                status    = kQ3Success;
  60.     
  61.     TQ3MacDrawContextData    theMacDrawContextData;
  62.     
  63.     if(!port) goto bail;
  64.     
  65.     /*
  66.     **    DrawContextData
  67.     */
  68.     #define mDCData theMacDrawContextData.drawContextData
  69.     
  70.     mDCData.clearImageMethod    = kQ3ClearMethodWithColor;
  71.     mDCData.clearImageColor        = white;
  72.     mDCData.paneState            = kQ3True;
  73.     
  74.     {
  75.         long    width    = (port->portRect.right - port->portRect.left) * 0.5,
  76.                 height    = (port->portRect.bottom - port->portRect.top) * 0.5;
  77.                 
  78.         mDCData.pane.min.x    =    (1.0 - paneSize) * width;
  79.         mDCData.pane.min.y    =    (1.0 - paneSize) * height;
  80.             
  81.         mDCData.pane.max.x    =    (paneSize + 1) * width;
  82.         mDCData.pane.max.y    =    (paneSize + 1) * height;
  83.     }
  84.         
  85.     mDCData.maskState            = kQ3False;
  86.     mDCData.doubleBufferState    = kQ3True;
  87.     
  88.     
  89.     /*
  90.     **    MAC DrawContextData
  91.     */
  92.     theMacDrawContextData.grafPort    = (CGrafPort *) port; 
  93.     theMacDrawContextData.viewPort    = NULL; 
  94.     theMacDrawContextData.window    = (CGrafPort *) port; 
  95.     theMacDrawContextData.library    = kQ3Mac2DLibraryQuickDraw;
  96.     
  97.     mBailIfNULL_(theDrawContext = Q3MacDrawContext_New(&theMacDrawContextData));
  98.     
  99. bail:
  100.     if (status == kQ3Failure) {
  101.     
  102.         if (theDrawContext) {
  103.         
  104.             Q3Object_Dispose(theDrawContext);
  105.             theDrawContext    = NULL;
  106.         }
  107.     }
  108.     
  109.     return (theDrawContext);
  110.  
  111. #undef mDCData
  112.  
  113. }
  114.  
  115.  
  116. TQ3ShaderObject    Q3ADUtility_NewShader(void)
  117. {
  118.     return Q3LambertIllumination_New();
  119. }
  120.  
  121.  
  122.  
  123.  
  124. /*===========================================================================*\
  125.  *
  126.  *    Routine:    Q3ADUtility_GetNumInRange()
  127.  *
  128.  *    Comments:    Returns a number within the range specified by width
  129.  *                and offset by offset. The number is parametrized within
  130.  *                "range" as below.
  131.  *
  132.  *                EXAMPLE:  0 ------------------- 1    width:    0.5
  133.  *                                | range  |             offset:    0.5
  134.  *
  135.  *                EXAMPLE:  0 ------------------- 1    width:    0.5
  136.  *                                      | range  |    offset:    1.0
  137.  *
  138.  *                EXAMPLE:  0 ------------------- 1    width:    0.25
  139.  *                                          |rnge|    offset:    1.0
  140.  *                
  141. \*===========================================================================*/
  142.  
  143. float        Q3ADUtility_GetNumInRange(
  144.                     float number,
  145.                     float offset,
  146.                     float width)
  147. {
  148.     if (width == 0.0)    return offset;
  149.     
  150.     if (offset == 0.0)    return (number * width);
  151.     
  152.     return (offset * (1 - width)) + (number * width);
  153. }
  154.  
  155.  
  156. /*===========================================================================*\
  157.  *
  158.  *    Routine:    Q3ADUtility_GetRectOfBestMonitor()
  159.  *
  160.  *    Comments:    Inputs the monitorsInfo data given by AD and returns the
  161.  *                Rect (in global coords) os the best monitor to draw into.
  162.  *                
  163. \*===========================================================================*/
  164.  
  165. Rect    Q3ADUtility_GetRectOfBestMonitor(
  166.             MonitorsInfoPtr monitorsInfo)
  167. {
  168.     int bestMonitor    = 0;
  169.     int    idx            = 0;
  170.  
  171.     assert(monitorsInfo);
  172.     
  173.     /*
  174.     **    Here, we go through the list of monitors we are given,
  175.     **    searching for the one with either the deepest bitdepth,
  176.     **    or the first one that is 16 bit
  177.     */
  178.     
  179.     for (idx = 0; idx < monitorsInfo->monitorCount; idx++)
  180.     {
  181.         if (monitorsInfo->monitorList[idx].curDepth == 16)
  182.         {
  183.             bestMonitor = idx;
  184.             goto done;
  185.         }
  186.         
  187.         
  188.         if (monitorsInfo->monitorList[idx].curDepth >
  189.             monitorsInfo->monitorList[bestMonitor].curDepth)
  190.         {
  191.             bestMonitor = idx;
  192.         }
  193.     }
  194.     
  195. done:
  196.     return monitorsInfo->monitorList[bestMonitor].bounds;
  197.  
  198. }
  199.  
  200.  
  201. /*===========================================================================*\
  202.  *
  203.  *    Routine:    Q3ADUtility_GetBestMonitor()
  204.  *
  205.  *    Comments:    Inputs the monitorsInfo data given by AD and returns the
  206.  *                best monitor to draw into.
  207.  *                
  208. \*===========================================================================*/
  209.  
  210. long    Q3ADUtility_GetBestMonitor(
  211.             MonitorsInfoPtr monitorsInfo)
  212. {
  213.     long bestMonitor    = 0;
  214.     int    idx            = 0;
  215.  
  216.     assert(monitorsInfo);
  217.     
  218.     /*
  219.     **    Here, we go through the list of monitors we are given,
  220.     **    searching for the one with either the deepest bitdepth,
  221.     **    or the first one that is 16 bit
  222.     */
  223.     
  224.     for (idx = 0; idx < monitorsInfo->monitorCount; idx++)
  225.     {
  226.         if (monitorsInfo->monitorList[idx].curDepth == 16)
  227.         {
  228.             bestMonitor = idx;
  229.             goto done;
  230.         }
  231.         
  232.         
  233.         if (monitorsInfo->monitorList[idx].curDepth >
  234.             monitorsInfo->monitorList[bestMonitor].curDepth)
  235.         {
  236.             bestMonitor = idx;
  237.         }
  238.     }
  239.     
  240. done:
  241.     return bestMonitor;
  242.  
  243. }
  244.  
  245.  
  246. /*===========================================================================*\
  247.  *
  248.  *    Routine:    TQ3Status_to_OSErr()
  249.  *
  250.  *    Comments:    Handles TQ3Statuses and returns an OSErr.
  251.  *                
  252. \*===========================================================================*/
  253.  
  254. OSErr    TQ3Status_to_OSErr(TQ3Status inStatus)
  255. {
  256.  
  257.     /*
  258.     **    there's got to be a better error to return than userCanceledErr
  259.     */
  260.     if (inStatus == kQ3Success)
  261.         return noErr;
  262.     else return userCanceledErr;
  263. }
  264.  
  265.  
  266.  
  267. #if 0
  268. #pragma mark -
  269. #endif
  270.  
  271. /*===========================================================================*\
  272.  *
  273.  *    Routine:    Offscreen_New()
  274.  *
  275.  *    Comments:    
  276.  *                
  277. \*===========================================================================*/
  278.  
  279. TQ3ADOffscreen *Offscreen_New(
  280.                     CGrafPtr        inDestPort,
  281.                     const Rect        *inDestRect,
  282.                     long            inDithered)
  283. {
  284.     Rect            gworldRect;
  285.     iTQ3ADOffscreen    *outOffscreen = NULL;
  286.     TQ3Status        status = kQ3Success;
  287.     
  288.     assert(inDestPort);
  289.     assert(inDestRect);
  290.     
  291.     mBailIfNULL_(outOffscreen = malloc(sizeof(iTQ3ADOffscreen)));
  292.  
  293.     /*
  294.     **    Save the internal preference as
  295.     **    to whether it should be dithered or not
  296.     */
  297.     outOffscreen->dithered = inDithered;
  298.     
  299.     /*
  300.     **    Saves off the destination port
  301.     */
  302.     outOffscreen->destPort = inDestPort;
  303.     
  304.     /*
  305.     **    Grabs the rect that we are supposed to draw into.
  306.     **    We also use it for the size for our own internal Gworld
  307.     */
  308.     outOffscreen->destRect = gworldRect = *inDestRect;
  309.     
  310.     /*
  311.     **    So now, we normalize the rect for our GWorld (which
  312.     **    we got from the above call)
  313.     */
  314.     OffsetRect(&gworldRect, -(gworldRect.top), -(gworldRect.left));
  315.     
  316.     /*
  317.     **    Allocate it
  318.     */
  319.     if (NewGWorld(
  320.             &outOffscreen->sourcePort,
  321.             16,
  322.             &gworldRect,
  323.             NULL,
  324.             NULL,
  325.             useTempMem)        == noErr)
  326.  
  327.     {
  328.         PixMapHandle     hPixMap;
  329.         CGrafPtr        savedPort;
  330.         GDHandle        savedGDevice;
  331.         
  332.         GetGWorld(&savedPort, &savedGDevice);
  333.         SetGWorld(outOffscreen->sourcePort, NULL);
  334.         
  335.         EraseRect(&outOffscreen->sourcePort->portRect);
  336.         
  337.         SetGWorld(savedPort, savedGDevice);
  338.  
  339.         hPixMap = GetGWorldPixMap (outOffscreen->sourcePort);
  340.         HLock ((Handle) hPixMap);
  341.         LockPixels (hPixMap);
  342.         
  343.     } else {
  344.         status = kQ3Failure;
  345.         goto bail;
  346.     }
  347.  
  348. bail:
  349.  
  350.     if (status == kQ3Failure) {
  351.         if (outOffscreen) {
  352.             free(outOffscreen);
  353.             outOffscreen = NULL;
  354.         }
  355.     }
  356.  
  357.     return outOffscreen;
  358.  
  359. }
  360.  
  361.  
  362. /*===========================================================================*\
  363.  *
  364.  *    Routine:    Offscreen_Dispose()
  365.  *
  366.  *    Comments:    
  367.  *                
  368. \*===========================================================================*/
  369.  
  370. TQ3Status Offscreen_Dispose(
  371.                 TQ3ADOffscreen    *ioOffscreen)
  372. {
  373.     if (ioOffscreen    == NULL)
  374.         return kQ3Success;
  375.     
  376.     {
  377.         GWorldPtr        tempGWorldPtr    = NULL;
  378.         PixMapHandle     hPixMap;
  379.         
  380.         tempGWorldPtr = ioOffscreen->sourcePort;
  381.         
  382.         hPixMap = GetGWorldPixMap (tempGWorldPtr);
  383.  
  384.         HUnlock ((Handle) hPixMap);
  385.         UnlockPixels (hPixMap);
  386.         
  387.         DisposeGWorld (tempGWorldPtr);
  388.         
  389.     }
  390.  
  391.     return kQ3Success;
  392.  
  393. }
  394.  
  395.  
  396. /*===========================================================================*\
  397.  *
  398.  *    Routine:    iOffscreen_ZeroOut()
  399.  *
  400.  *    Comments:    
  401.  *                
  402. \*===========================================================================*/
  403.  
  404. TQ3Status    iOffscreen_ZeroOut(
  405.                 iTQ3ADOffscreen *ioOffscreen)
  406. {
  407.     assert(ioOffscreen);
  408.     
  409.     ioOffscreen->sourcePort            = NULL;
  410.     ioOffscreen->destPort            = NULL;
  411.     ioOffscreen->destRect.top        =
  412.     ioOffscreen->destRect.bottom    =
  413.     ioOffscreen->destRect.left        =
  414.     ioOffscreen->destRect.right        = 0;
  415.     ioOffscreen->dithered            = 1;
  416.     
  417.     return kQ3Success;
  418. }
  419.  
  420.  
  421.  
  422.  
  423. /*===========================================================================*\
  424.  *
  425.  *    Routine:    Offscreen_Blit()
  426.  *
  427.  *    Comments:    
  428.  *                
  429. \*===========================================================================*/
  430.  
  431. TQ3Status    Offscreen_Blit(
  432.                 TQ3ADOffscreen *inOffscreen)
  433. {
  434.     
  435.     assert(inOffscreen);
  436.     
  437.     {
  438.         /*
  439.         **    Sorry this is so ugly.
  440.         */
  441.         
  442.         /*
  443.         **    we have to save the last port
  444.         */
  445.         GWorldPtr        savedPort;
  446.         GDHandle        tempGDHandle;
  447.         
  448.         /*
  449.         **    These are used for *one* call, that being the one to CopyBits
  450.         **    setting up the environment just so, will allow the fastest
  451.         **    blitting
  452.         */
  453.         
  454.         RGBColor        savedForeground,
  455.                         savedBackground;
  456.         RGBColor        white                = {0xFFFF, 0xFFFF, 0xFFFF};
  457.         RGBColor         black                = {0, 0, 0};
  458.         PixMapHandle     offscreenBitmap        = NULL;
  459.         PixMapHandle     destBitmap            = NULL;
  460.  
  461.         /*
  462.         **    save off the port
  463.         */
  464.         GetGWorld((GWorldPtr*)&savedPort, &tempGDHandle);
  465.         
  466.         /*
  467.         **    now, we get ready to CopyBits. There is some setup to make it
  468.         **    fast, so we do that first.
  469.         */
  470.         GetForeColor (&savedForeground);
  471.         GetBackColor (&savedBackground);
  472.         
  473.         RGBForeColor (&black);
  474.         RGBBackColor (&white);
  475.  
  476.         /*
  477.         **    Grab the source and destination pixmaps
  478.         */
  479.         offscreenBitmap = GetGWorldPixMap (inOffscreen->sourcePort);
  480.         destBitmap = GetGWorldPixMap (inOffscreen->destPort);
  481.  
  482.         /*
  483.         **    Now for God knows why, we have to set the GWorld to the
  484.         **    *destination* of our CopyBits or prepare to Restart.
  485.         */
  486.         SetPort((GrafPort *)inOffscreen->destPort);
  487.         
  488.         
  489.         /*
  490.         **    Again, for God knows why, we have to do a PenNormal here
  491.         **    or CopyBits works weird.
  492.         */
  493.         PenNormal();
  494.         
  495.         /*
  496.         **    do it.
  497.         **    BTW, we use the fOffscreen->portRect twice because it's
  498.         **    at 0,0 and that's what we want.
  499.         */
  500.         inOffscreen->dithered ?
  501.         
  502.         CopyBits ((const struct BitMap *)*offscreenBitmap,
  503.                   (const struct BitMap *)*destBitmap,
  504.                   &inOffscreen->sourcePort->portRect, 
  505.                   &inOffscreen->destRect,
  506.                   srcCopy | ditherCopy, 0L)
  507.                   
  508.                   :
  509.                   
  510.         CopyBits ((const struct BitMap *)*offscreenBitmap,
  511.                   (const struct BitMap *)*destBitmap,
  512.                   &inOffscreen->sourcePort->portRect, 
  513.                   &inOffscreen->destRect,
  514.                   srcCopy, 0L)
  515.                   
  516.                   ;
  517.         
  518.         /*
  519.         **    Restore all that stuff
  520.         */
  521.         RGBForeColor (&savedForeground);
  522.         RGBBackColor (&savedBackground);
  523.         
  524.         /*
  525.         **    We can't forget to restore our original port
  526.         */
  527.         SetGWorld((CGrafPtr)savedPort, tempGDHandle);
  528.         
  529.     }
  530.             
  531.     return    kQ3Success;
  532.  
  533. bail:
  534.     return    kQ3Failure;
  535. }
  536.  
  537.  
  538.  
  539. /*===========================================================================*\
  540.  *
  541.  *    Routine:    Offscreen_NewPixmapDrawContext()
  542.  *
  543.  *    Comments:    
  544.  *                
  545. \*===========================================================================*/
  546.  
  547. TQ3DrawContextObject    Offscreen_NewPixmapDrawContext(
  548.                             TQ3ADOffscreen *inOffscreen)
  549. {
  550.     TQ3DrawContextObject    theDrawContext    = NULL;
  551.     TQ3ColorARGB            white    = { 1.0, 0.0, 0.0, 0.0 };
  552.     TQ3Status                status    = kQ3Success;
  553.     
  554.     TQ3PixmapDrawContextData    thePixmapDrawContextData;
  555.     
  556.     assert(inOffscreen);
  557.  
  558.     #define    mDCData    thePixmapDrawContextData.drawContextData
  559.     
  560.     mDCData.clearImageMethod    = kQ3ClearMethodWithColor;
  561.     mDCData.clearImageColor        = white;
  562.     mDCData.paneState            = kQ3False;
  563.     mDCData.maskState            = kQ3False;
  564.     mDCData.doubleBufferState    = kQ3False;
  565.         
  566.     #define    mPixmapData    thePixmapDrawContextData.pixmap
  567.     
  568.     mPixmapData.image = GetPixBaseAddr (inOffscreen->sourcePort->portPixMap);
  569.  
  570.     mPixmapData.width        = inOffscreen->sourcePort->portRect.right -
  571.                                 inOffscreen->sourcePort->portRect.left;
  572.                                 
  573.     mPixmapData.height        = inOffscreen->sourcePort->portRect.bottom -
  574.                                 inOffscreen->sourcePort->portRect.top;
  575.                                 
  576.     mPixmapData.rowBytes    = (**(inOffscreen->sourcePort->portPixMap)).rowBytes & 0x3FFF;    
  577.     mPixmapData.pixelSize    = (**(inOffscreen->sourcePort->portPixMap)).pixelSize;    
  578.  
  579.     switch((**(inOffscreen->sourcePort->portPixMap)).pixelSize)
  580.     {
  581.         case 16:
  582.         mPixmapData.pixelType = kQ3PixelTypeRGB16;
  583.         break;
  584.         
  585.         case 32:
  586.         mPixmapData.pixelType = kQ3PixelTypeRGB32;
  587.         break;
  588.         
  589.         default:
  590.         goto bail;
  591.         break;
  592.     };
  593.     
  594.     mPixmapData.bitOrder    = kQ3EndianBig;    
  595.     mPixmapData.byteOrder    = kQ3EndianBig;    
  596.  
  597.     mBailIfNULL_(theDrawContext = Q3PixmapDrawContext_New(&thePixmapDrawContextData));
  598.  
  599.  
  600. bail:
  601.     if (status == kQ3Failure) {
  602.         if (theDrawContext) {
  603.             Q3Object_Dispose(theDrawContext);
  604.             theDrawContext    = NULL;
  605.         }
  606.     }
  607.     
  608.     return theDrawContext;
  609.  
  610. #undef mPixmapData
  611. #undef mDCData
  612.  
  613. }
  614.  
  615.